package com.intel.factorytest.activity;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.GridView;

import com.intel.factorytest.R;
import com.intel.factorytest.adapter.GridAdapter;
import com.intel.factorytest.application.MATApplication;
import com.intel.factorytest.log.LogWriter;
import com.intel.factorytest.util.Util;

public class SensorsTestActivity extends BaseActivity {
    
    private static final String NAME = "Sensors";
    private static final String TAG = "SensorsTest";
    // Ambient Light Sensor=1;Accelerometer=1;Compass=1;Gyroscope=1;Proximity=1
    private static final String AmbientLightSensor = "Ambient Light Sensor";
    private static final String AccelerometerSensor = "Accelerometer";
    private static final String ProximitySensor = "Proximity";
    
    private static final String AmbientLightSensor_zh = "光感应器";
    private static final String AccelerometerSensor_zh = "加速器";
    private static final String ProximitySensor_zh = "近距离感应器";
    
    private static final Map<String, String> nameMapping_language = new HashMap<String, String>();
    static {
        nameMapping_language.put(AccelerometerSensor, AccelerometerSensor_zh);
        nameMapping_language.put(AmbientLightSensor, AmbientLightSensor_zh);
        nameMapping_language.put(ProximitySensor, ProximitySensor_zh);
    }
    
    private static final int INDEX_Accelerometer = 0;
    private static final int INDEX_AmbientLights = 1;
    private static final int INDEX_Proximity = 2;
    
    private int lenX = 0;
    private int lenY = 0;
    
    private int contentHeight = 0;
    
    // Sensors value format: Sensors=1;Ambient Light Sensor=1;Accelerometer=1;Compass=1;GyroTest=1;Proximity=1
    private String confValue;
    
    // test switch configuration
    private boolean doAmbientLightSensorTest = false;
    private boolean doAccelrometerSensorTest = false;
    private boolean doCompassSensorTest = false;
    private boolean doGyroSensorTest = false;
    private boolean doProximitySensorTest = false;
    private boolean doBarometerSensorTest = false;
    
    // single item test Result
    private boolean resultAmbientLightOK = false;
    private boolean resultAccelrometerOK = false;
    private boolean resultCompassOK = false;
    private boolean resultGyroscopeOK = false;
    private boolean resultProximityOK = false;    
    private boolean resultBarometerOK = false;
    
    private float a_sensor_value = -1;
    private float p_sensor_value = -1;
    
    // sensors
    private SensorManager mSensorManager;
    private Sensor mAmbientLightSensor;
    private Sensor mAccelerometerSensor;
    private Sensor mCompassSensor;
    private Sensor mGyroSensor;
    private Sensor mProximitySensor;    
    private Sensor mBarometerSensor;
    
    // Timer
    private Timer mTimer_CheckResult = null;
    
    // Handler Message
    private static final int MSG_CHECK_RESULT = 1;
    
    // test result
    
    // layout
    private GridView mGridview;
    private GridAdapter mGridAdapter;
    private List<ItemInfo> mInfoList = new ArrayList<ItemInfo>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        
        setContentView(R.layout.sensor_gridview);
        initView();
        initInfoList();
        mGridview = (GridView) findViewById(R.id.gridview);
        mGridAdapter = new GridAdapter(this, mInfoList);
        mGridview.setAdapter(mGridAdapter);
        
        
        initSensors();
        
        Log.d(TAG, "isSystemTest = "+isSystemTest);
        if (isSystemTest) {
            confValue = getIntent().getStringExtra("value");
            Log.d(TAG, "confValue = "+confValue);
            initTestByConfig(confValue);
        } else {
            doAmbientLightSensorTest = true;
            doAccelrometerSensorTest = true;
            doProximitySensorTest = true;
            doGyroSensorTest = true;
            doBarometerSensorTest = true;

            mInfoList.get(INDEX_Accelerometer).toTest = doAccelrometerSensorTest;
            mInfoList.get(INDEX_AmbientLights).toTest = doAmbientLightSensorTest;
            mInfoList.get(INDEX_Proximity).toTest = doProximitySensorTest;
        }
        
        startSensorsTest();
        
        // check result
        startCheck();
        
    }
    
    @Override
    protected void initView() {
        super.initView();
        mSucBtn.setVisibility(View.INVISIBLE);
        mFailBtn.setVisibility(View.VISIBLE);
        // mSucBtn.setBackgroundColor(Color.argb(255, 255, 255, 0));
        // mFailBtn.setBackgroundColor(Color.argb(255, 255, 255, 0));
        mRepeatBtn.setBackgroundColor(Color.argb(255, 255, 255, 0));
    }
    
    private void initInfoList() {
        ItemInfo ambientligthInfo = ItemInfo.getInstance(getString(R.string.SensorsAmbientLightSensor), "", doAmbientLightSensorTest, false, false);
        ItemInfo accelerometerInfo = ItemInfo.getInstance(getString(R.string.SensorsAccelerometerSensor)/*nameMapping.get(AccelerometerSensor)*/, "", doAccelrometerSensorTest, false, false);
        ItemInfo proximityInfo = ItemInfo.getInstance(getString(R.string.SensorsProximity), "", doProximitySensorTest, false, false);
        
        mInfoList.add(accelerometerInfo); // index = 0;
        mInfoList.add(ambientligthInfo); // index = 1;
        mInfoList.add(proximityInfo); // index = 2;
    }
    
    public static class ItemInfo {
        public String name;
        public String value;
        public boolean toTest;
        public boolean isAvaliable;
        public boolean isRedBg;
        
        private ItemInfo(String name, String value, boolean toTest, boolean isAvaliable, boolean isRedBg) {
            this.name = name;
            this.value = value;
            this.toTest = toTest;
            this.isAvaliable = isAvaliable;
            this.isRedBg = isRedBg;
        }
        
        public static ItemInfo getInstance(String name, String value, boolean toTest, boolean isAvaliable, boolean isRedBg) {
            return new ItemInfo(name, value, toTest, isAvaliable, isRedBg);
        }
    }
    
    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        Log.d(TAG, "doAmbientLightSensorTest = "+doAmbientLightSensorTest);
        Log.d(TAG, "doAccelrometerSensorTest = "+doAccelrometerSensorTest);
        Log.d(TAG, "doProximitySensorTest = "+doProximitySensorTest);
        Log.d(TAG, "doGyroSensorTest = "+doGyroSensorTest);
        Log.d(TAG, "doBarometerSensorTest = "+doBarometerSensorTest);
        if (doAmbientLightSensorTest) {
            mSensorManager.registerListener(mAmbientLightSel, mAmbientLightSensor, SensorManager.SENSOR_DELAY_FASTEST);
        }
        if (doAccelrometerSensorTest) {
            mSensorManager.registerListener(mAccelerometerSel, mAccelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
        }
        if (doProximitySensorTest) {
            mSensorManager.registerListener(mProximitySel, mProximitySensor, SensorManager.SENSOR_DELAY_GAME);
        }
    }
    
    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        if (doAmbientLightSensorTest) {
            mSensorManager.unregisterListener(mAmbientLightSel);
        }
        if (doAccelrometerSensorTest) {
            mSensorManager.unregisterListener(mAccelerometerSel);
        }
        if (doProximitySensorTest) {
            mSensorManager.unregisterListener(mProximitySel);
        }
        if (mTimer_CheckResult != null) {
            mTimer_CheckResult.cancel();
        }
    }
    
    private void initSensors() {
        mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
        mAmbientLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
        mAccelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
        mCompassSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        mGyroSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
        mBarometerSensor= mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE);
        List<Sensor> list = mSensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
        Log.d(TAG, "list.size = "+list.size());
        Log.d(TAG, "AmbientLightSensor=" + mAmbientLightSensor);
        Log.d(TAG, "AccelerometerSensor=" + mAccelerometerSensor);
        Log.d(TAG, "ProximitySensor=" + mProximitySensor);
        Log.d(TAG, "CompassSensor=" + mCompassSensor);
        Log.d(TAG, "GyroSensor=" + mGyroSensor);        
        Log.d(TAG, "BarometerSensor=" + mBarometerSensor);
    }
    
    private void startSensorsTest() {
        if (doAmbientLightSensorTest) {
            testAmbientLightSensor();
        }
        if (doAccelrometerSensorTest) {
            testAccelerometerSensor();
        }
        if (doProximitySensorTest) {
            testProximitySensor();
        }
    }
    
    
    private void initTestByConfig(String config) {
        if (config == null || config.trim().length() == 0) return;
        
        Log.i(TAG,"sensors config = " + config);
        
        String[] configs = config.split(";");
        for (String conf : configs) {
            String[] items = conf.split("=");
            
            // overall sensors' switch
            if (items.length == 1) {
                if (items[0].equals("0")) {
                    // Don't test any Sensor!
                    break;
                }
                continue;
            }
            
            // single sensor's switch
            boolean doTest = false;
            if (items[1].equals("1")) {
                doTest = true;
            }
            
            if (items[0].equals(AmbientLightSensor)) {
                doAmbientLightSensorTest = doTest;
                mInfoList.get(INDEX_AmbientLights).toTest = doAmbientLightSensorTest;
            } else if (items[0].equals(AccelerometerSensor)) {
                doAccelrometerSensorTest = doTest;
                mInfoList.get(INDEX_Accelerometer).toTest = doAccelrometerSensorTest;
            }  else if (items[0].equals(ProximitySensor)) {
                doProximitySensorTest = doTest;
                mInfoList.get(INDEX_Proximity).toTest = doProximitySensorTest;
            }
            
        }
    }
    
    private Handler mHandler_CheckResult = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MSG_CHECK_RESULT:
                SensorsTestActivity.this.checkResult();
                break;

            default:
                break;
            }
        }
         
     };
    
    private void checkResult() {
         if ((!mInfoList.get(INDEX_AmbientLights).toTest || mInfoList.get(INDEX_AmbientLights).toTest && mInfoList.get(INDEX_AmbientLights).isAvaliable)
                 && (!mInfoList.get(INDEX_Accelerometer).toTest || mInfoList.get(INDEX_Accelerometer).toTest && mInfoList.get(INDEX_Accelerometer).isAvaliable)
                 && (!mInfoList.get(INDEX_Proximity).toTest || mInfoList.get(INDEX_Proximity).toTest && mInfoList.get(INDEX_Proximity).isAvaliable)){
             mSucBtn.setVisibility(View.VISIBLE);
         } else {
             mSucBtn.setVisibility(View.INVISIBLE);
         }
     }
     
     private void startCheck() {
         mTimer_CheckResult = new Timer();
         TimerTask task = new TimerTask() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                mHandler_CheckResult.sendEmptyMessage(MSG_CHECK_RESULT);
            }
        };
        mTimer_CheckResult.schedule(task, 500, 1000);
     }
    
    @Override
    public void finish() {
        isLogged = true;
        super.finish();
    }
    
    
    private boolean isAllSensorsTestOK() {
        boolean ambientLightOK = false;
        boolean accelerometerOK = false;
        boolean compassOK = false;
        boolean gyroscopeOK = false;
        boolean proximityOK = false;        
        boolean barometerOK = false;
        
        if (doAmbientLightSensorTest) {
            if (resultAmbientLightOK) {
                ambientLightOK = true;
            }
        } else {
            ambientLightOK = true;
        }
        
        if (doAccelrometerSensorTest) {
            if (resultAccelrometerOK) {
                accelerometerOK = true;
            }
        } else {
            accelerometerOK = true;
        }
        
        if (doCompassSensorTest) {
            if (resultCompassOK) {
                compassOK = true;
            }
        } else {
            compassOK = true;
        }
        
        if (doProximitySensorTest) {
            if (resultProximityOK) {
                proximityOK = true;
            }
        } else {
            proximityOK = true;
        }
        
        if (doGyroSensorTest) {
            if (resultGyroscopeOK) {
                gyroscopeOK = true;
            }
        } else {
            gyroscopeOK = true;
        }

        if (doBarometerSensorTest) {
            if (resultBarometerOK) {
                barometerOK = true;
            }
        } else {
            barometerOK = true;
        }
        return ambientLightOK && accelerometerOK && proximityOK && gyroscopeOK && barometerOK;
    }
    
    private String testcaseResultsInfo() {
        StringBuilder sb = new StringBuilder();
        Iterator<SensorsTestActivity.ItemInfo> it = mInfoList.iterator();
        while(it.hasNext()) {
            SensorsTestActivity.ItemInfo itemInfo = it.next();
            sb.append("\n").append(itemInfo.name).append(itemInfo.isAvaliable ? " 成功 " : "失败 ").append("测试结果：").append(itemInfo.value).append("\n");
        }
        return sb.toString();
    }
    
    // #######################################################################
    // #                    AmbientLightSensor                                 #
    // #######################################################################
    
    private SensorEventListener mAmbientLightSel = new SensorEventListener() {

        @Override
        public void onSensorChanged(SensorEvent event) {
            int value_0 = (int)event.values[0];
            //Log.i(TAG, "onSensorChanged, timestamp: " + value_0);
            
//            System.out.println("tangjun sensor test : AmbientLightSensor value=" + value_0);
            
            if (a_sensor_value >= 0 && a_sensor_value != value_0) {
                mInfoList.get(INDEX_AmbientLights).isAvaliable = true;
                resultAmbientLightOK = true;
            }
            mInfoList.get(INDEX_AmbientLights).value = getString(R.string.SERVICEMENU_ALS_VALUE_TXT) + " " +value_0; // .put(AmbientLightSensor, getString(R.string.SERVICEMENU_ALS_VALUE_TXT) + " " +value_0);
            a_sensor_value = value_0;
            
            mGridAdapter.notifyDataSetChanged();
        }
        
        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            
        }        
    };
    
    private void testAmbientLightSensor() {
        if (mAmbientLightSensor == null) {
            Log.d(TAG, "Cannot detect sensors. Not enabled");
            mInfoList.get(INDEX_AmbientLights).value = getString(R.string.SERVICEMENU_ALSENSOR_NULL_TXT); // .put(AmbientLightSensor, getString(R.string.SERVICEMENU_ALSENSOR_NULL_TXT));
        } else {
            Log.i(TAG, "ALS sensors avaliable");
            mInfoList.get(INDEX_AmbientLights).value = getString(R.string.SERVICEMENU_ALS_START_TXT); // put(AmbientLightSensor, getString(R.string.SERVICEMENU_ALS_START_TXT));
        }
        mGridAdapter.notifyDataSetChanged();
    }
    
    // #######################################################################
    // #                    AccelerometerSenesor                             #
    // #######################################################################
    
    private float gx1_as = 0;
    private float gy1_as = 1;
    private float gz1_as = 2;
    private float gx_as = 0;
    private float gy_as = 1;
    private float gz_as = 2;
    private int count_as = 0;
    private String message_as = null; 
    
    private void testAccelerometerSensor() {
        if(mAccelerometerSensor == null){
            mInfoList.get(INDEX_Accelerometer).value = getString(R.string.SERVICEMENU_ACCELEROMETER_GENSER_NULL_TXT); // .put(AccelerometerSensor, getString(R.string.SERVICEMENU_ACCELEROMETER_GENSER_NULL_TXT));
        }
        mGridAdapter.notifyDataSetChanged();
    }
    
    private SensorEventListener mAccelerometerSel = new SensorEventListener() {
        
        @Override
        public void onSensorChanged(SensorEvent event) {
            long currentTimeMillis = System.currentTimeMillis();
            if (count_as == 0) {
                gx_as = event.values[0];
                gy_as = event.values[1];
                gz_as = event.values[2];
                message_as    = " X:"+Util.reserve2decimals(gx_as)+"\n Y:"+Util.reserve2decimals(gy_as)+"\n Z:"+Util.reserve2decimals(gz_as);
            }else {
                gx1_as = event.values[0];
                gy1_as = event.values[1];
                gz1_as = event.values[2];
                message_as    = " X:"+Util.reserve2decimals(gx1_as)+"\n Y:"+Util.reserve2decimals(gy1_as)+"\n Z:"+Util.reserve2decimals(gz1_as);
            }
            count_as++;
            is_pass = false;
            if(count_as >= 40) {
                if (gx_as!=gx1_as || gy_as!=gy1_as || gz_as!=gz1_as) {
                    is_pass = true;
                    message_as = message_as + "\n" + getString(R.string.SERVICEMENU_GSENSOR_IS_SUCCESS);
                }else {
                    is_pass = false;
                }
            }
            if (is_pass) {
                mInfoList.get(INDEX_Accelerometer).isAvaliable = true;
                resultAccelrometerOK = true;
            }
            mInfoList.get(INDEX_Accelerometer).value = message_as; // .put(AccelerometerSensor, message_as);
            mGridAdapter.notifyDataSetChanged();
        }
        
        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            // TODO Auto-generated method stub
            
        }
    };
    
    // #######################################################################
    // #                    ProximitySenesor                             #
    // #######################################################################
    
    private String mDistance_prox="";
    private String tmp_prox = null;  
    
    private void testProximitySensor() {
        mDistance_prox = getResources().getString(R.string.SERVICEMENU_PROXIMITY_DISTANCE_TXT);
        Log.i(TAG,"msensor:" + mProximitySensor);
        if(mProximitySensor == null) {
            mInfoList.get(INDEX_Proximity).value = getString(R.string.SERVICEMENU_APROXIMITY_FAILED_TXT); // .put(ProximitySensor, getString(R.string.SERVICEMENU_APROXIMITY_FAILED_TXT));
            is_pass = false;
        }else
        {
            
        }
        mGridAdapter.notifyDataSetChanged();
    }
    
    private SensorEventListener mProximitySel = new SensorEventListener() {

        @Override
        public void onSensorChanged(SensorEvent event) {
            // TODO Auto-generated method stub
            int type = event.sensor.getType();
            
            if (type == Sensor.TYPE_PROXIMITY) {
                //Log.d(TAG, "p_sensor_value:"+p_sensor_value);
                if (p_sensor_value >= 0 && event.values[0] != p_sensor_value){
                    mInfoList.get(INDEX_Proximity).isRedBg = false;
                    resultProximityOK = true;
                    mInfoList.get(INDEX_Proximity).isAvaliable = true;
                }
                p_sensor_value = event.values[0];
                tmp_prox = mDistance_prox + p_sensor_value;
                tmp_prox = tmp_prox  + "\n" +getString(R.string.SensorsProximityAvailable);

                mInfoList.get(INDEX_Proximity).value = tmp_prox; // .put(ProximitySensor, tmp_prox);
                //mInfoList.get(INDEX_Proximity).isAvaliable = true;
                mGridAdapter.notifyDataSetChanged();
                Log.i(TAG, "SensorsTestActivity onSensorChanged type=" + type + " tmp_prox=" + tmp_prox);
            }
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            // TODO Auto-generated method stub

        }
    };

    
}
